package com.apexedu.eas.proxy;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.apexedu.eas.annotation.Query;
import com.apexedu.eas.common.SysContent;
import com.apexedu.eas.common.SysProperty;
import com.apexedu.eas.dao.impl.AopLogDao;
import com.apexedu.eas.entity.TAopLog;
import com.apexedu.eas.entity.TSqlLog;
import com.apexedu.eas.exception.EasException;
import com.apexedu.eas.thread.LogConsumer;
import com.apexedu.eas.util.DateUtil;
import com.apexedu.eas.util.LittleTimer;
import com.apexedu.eas.util.ProcUtil;
import com.apexedu.framework.dao.BaseDao;
import com.apexedu.framework.util.ConfigUtil;
import com.apexedu.framework.util.DBUtil;
import com.apexedu.framework.util.Pager;

@Aspect
@Component
public class MyInterceptor {
	private static Logger log = LoggerFactory.getLogger(MyInterceptor.class);
	private static String[] types = { "java.lang.Integer", "java.lang.Double", "java.lang.Float", "java.lang.Long",
			"java.lang.Short", "java.lang.Byte", "java.lang.Boolean", "java.lang.Char", "java.lang.String", "int",
			"double", "long", "short", "byte", "boolean", "char", "float" };

	@Resource
	protected BaseDao baseDao;

	public MyInterceptor() {
		log.debug("MyInterceptor 类已被spring容器管理");
	}

	private Pattern p1 = Pattern.compile("@(.+?)[ '\\)]");
	private Pattern p2 = Pattern.compile("@(.+)$");
	private static Pattern p3 = Pattern.compile("#\\{(.+?)\\}");
	private Map<Method, String [] > paramNamesMap =new HashMap<Method, String[]>();
	public static boolean enable = true;
	static{
		String time=null;
		String size =null; 
		try {
			enable=ConfigUtil.getString("aop_enable").toLowerCase().trim().equals("true")? true : false;
		} catch (Exception e) {
			log.error("在配置文件：config.properties中获取属性:aop_enable出现错误，将使用默认值:true");
		}
		
	}
	/*
	 * @Around("execution (* com.apexedu.eas.repository.*.*(..))") public Object
	 * repositoryFilter(ProceedingJoinPoint point) throws Throwable {
	 * System.out.println("-----------------------------------------"); Object o
	 * = point.proceed(point.getArgs()); return null; }
	 */
	// && !execution (* com.apexedu.framework.util.DBUtil.callProc*(..))

	private int getPager(Object[] os) {
		for(int i =0 ; i <os.length ;i++) {
			if (os[i] instanceof Pager) {
				return i;
			}
		}
		return -1;
	}

	private int getSqlArgIndex(String[] names , String str) {
		for (int i = 0; i < names.length; i++) {
			if (str.equals(names[i].toLowerCase())) {
				return i;
			}
		}
		return -1;
	}
	
	@Around("execution (* com.apexedu.eas.dao.impl.EasDBUtil.*(..))")
	public Object dbUtilFilter(ProceedingJoinPoint point) throws Throwable {
		Method method = ((MethodSignature) (point.getSignature())).getMethod();
		log.debug("dbUtilFilter拦截到方法：{}", method.getName());
		TSqlLog sqlLog = new TSqlLog(UUID.randomUUID().toString().replaceAll("\\-", ""));
		sqlLog.setStartTime(DateUtil.getDateTimeFormat(new Date()));
		sqlLog.setIp(getRemortIp(SysContent.getRequest()));
		LittleTimer timer = new LittleTimer(); // 计时器
		Class clazz= point.getTarget().getClass();
		String clazzName = clazz.getName();
		String methodName = point.getSignature().getName();
		String[] paramNames =paramNamesMap.get(method);
		if(paramNames==null){  //从缓存中取方法的参数信息
			paramNamesMap.put(method, getFieldsName(this.getClass(), clazzName, methodName));
			paramNames =paramNamesMap.get(method);
		}
		String logContent = writeLogInfo(paramNames, point, "sql");
		sqlLog.setParameter(logContent);
		sqlLog.setFunctionName(methodName);
		sqlLog.setClassName(clazzName);
		sqlLog.setState("normal");
		try {
			// 查找sql字符串
			for (int i = 0; i < paramNames.length; i++) {
				if (paramNames[i].toLowerCase().equals("sql")) {
					sqlLog.setSql(point.getArgs()[i].toString());
					log.debug("执行sql :{} ", sqlLog.getSql());
					break;
				}
			}
			return point.proceed(point.getArgs());
		} catch (Exception e) {
			sqlLog.setState("error");
			String ex = e.toString();
			String stackTrace = "";
			StackTraceElement[] st = e.getStackTrace();
			int len = st.length > 20 ? 20 : st.length;
			for (int i = 0; i < len; i++) {
				stackTrace += st[i] + "    \r\n";
			}
			sqlLog.setStackTrace(stackTrace);
			sqlLog.setExceptionInfo(ex);
			log.error("<<{}>> 执行sql语句出现错误   error: {} ", clazzName, e);
			throw e;
		} finally {
			try {
				long t = timer.end();
				log.debug("<<{}>> {} end , diff : {} ms", clazzName, methodName, t);
				sqlLog.setTimeDiff(t);
//				saveSqlLog(sqlLog);
				//LogConsumer.sqlLogQueue.add(sqlLog); // 此处使用add方法，不使用put，以免造成线程堵塞，影响系统正常工作
			} catch (Exception e2) {
				log.error("<<{}>> {} 保存sql执行记录日志出现未知错误！ ", clazzName, methodName, e2);
			}
		}
	}

	
	@SuppressWarnings("unchecked")
	@Around("execution (* com.apexedu.eas.dao.impl.*Dao.*(..))")
	public Object queryFilter(ProceedingJoinPoint point) throws Throwable {
		Method method = ((MethodSignature) (point.getSignature())).getMethod();
		System.out.println("MyInterceptor中dbUtilFilter方法拦截到的方法名称:"+method.getName());
		Query q = method.getAnnotation(Query.class);
		if (q != null) {
			TSqlLog sqlLog = new TSqlLog(UUID.randomUUID().toString().replaceAll("\\-", ""));
			sqlLog.setStartTime(DateUtil.getDateTimeFormat(new Date()));
			sqlLog.setIp(getRemortIp(SysContent.getRequest()));
			LittleTimer timer = new LittleTimer(); // 计时器
			Class clazz= point.getTarget().getClass();
			String clazzName = clazz.getName();
			String methodName = point.getSignature().getName();
			String[] paramNames =paramNamesMap.get(method);
			if(paramNames==null){  //从缓存中取方法的参数信息
				paramNamesMap.put(method, getFieldsName(this.getClass(), clazzName, methodName));
				paramNames =paramNamesMap.get(method);
			}
			String logContent = writeLogInfo(paramNames, point);
			sqlLog.setParameter(logContent);
			sqlLog.setFunctionName(methodName);
			sqlLog.setClassName(clazzName);
			sqlLog.setState("normal");
			Object [] args =point.getArgs();
			try {
				log.debug("queryFilter拦截到方法：{}", method.getName());
				String sql = q.value();
				boolean nativeQuery = q.nativeQuery();
				Class<?> cls = method.getReturnType();
				Pager pager = null;
				if (q.pager()) {
					// 需要分页
					int  i = getPager(args);
					pager=(Pager) args[i]; 
					args = ArrayUtils.remove(args, i);
					if (pager == null) {
						throw new EasException(EasException.PAGER_ERROR, null);
					}
				}
				if (nativeQuery) {
					boolean replace = q.replace();
					boolean splice = q.splice();
					if (replace) {
						Matcher m = p1.matcher(sql);
						while (m.find()) {
							String s = m.group(1);
							String v = SysProperty.MAPING.get(s);
							sql = sql.replaceAll("@" + s, v);
							log.debug("已替换实体名:{} 为数据库表名:{}", s, v);
						}
						if (sql.indexOf("@") != -1) {
							Matcher m1 = p2.matcher(sql);
							while (m1.find()) {
								String s = m1.group(1);
								String v = SysProperty.MAPING.get(s);
								sql = sql.replaceAll("@" + s, v);
								log.debug("已替换实体名:{} 为数据库表名:{}", s, v);
							}
						}
					}
					if(splice){
						Matcher m = p3.matcher(sql);
						while (m.find()) {
							String s = m.group(1);
							int index=getSqlArgIndex(paramNames, s.toLowerCase().trim());
							String v=args[index].toString();
							args = ArrayUtils.remove(args, index);
							sql=sql.replaceAll("#\\{"+s+"\\}", v );
							log.debug("已将sql中的变量:{}替换 为:{}", s, v);
						}
					}
					log.debug("执行sql :{} ", sql);
					sqlLog.setSql(sql); // 存储sql
					if (q.count()) {
						if (cls.isAssignableFrom(int.class) || cls.isAssignableFrom(Integer.class)) {
							return DBUtil.count(sql, args);
						} else if (cls.isAssignableFrom(long.class) || cls.isAssignableFrom(Long.class)) {
							return DBUtil.countForLong(sql, args);
						} else {
							log.error("方法：{} ，返回值类型错误", method.getName());
							return null;
						}
					} else if (q.update()) {
						if (args != null && args.length > 0)
							return DBUtil.executeSQL(sql, args);
						else
							return DBUtil.executeOneoffSQL(sql);

					} else if (q.procOut()){
							return  ProcUtil.callProcQueryOut(sql, args);
					}else {
						// 返回一个List
						if (List.class.isAssignableFrom(cls)) {
							Type type = method.getGenericReturnType();
							Type[] typesto = null;
							if (type instanceof ParameterizedType) { // 判断获取的类型是否是参数类型
								typesto = ((ParameterizedType) type).getActualTypeArguments();// 强制转型为带参数的泛型类型，
								// getActualTypeArguments()方法获取类型中的实际类型，如map<String,Integer>中的
								// String，integer因为可能是多个，所以使用数组
								// for (Type type2 : typesto) {
								// System.out.println("泛型类型" +((Class) type2) );
								// }
							}
							if (typesto != null) {
								Class retCls = null;
								// System.out.println(typesto[0].getClass());
								if (typesto[0] instanceof ParameterizedType) {
									retCls = (Class<?>) ((ParameterizedType) typesto[0]).getRawType();
								} else {
									retCls = (Class<?>) typesto[0];
								}
								// 返回类型的泛型类型是否为Map
								if (retCls.isAssignableFrom(Map.class)) {
									return q.pager() ? DBUtil.queryForList(pager, sql, args)
											: DBUtil.queryForList(sql, args);
								} else {
									return q.pager() ? DBUtil.queryPageBeanList(pager, sql, retCls, args)
											: DBUtil.queryAllBeanList(sql, retCls, args);
								}
							} else
								return q.pager() ? DBUtil.queryPageList(pager, sql, args)
										: DBUtil.queryAllList(sql, args);
						} else if (Object[].class.isAssignableFrom(cls)) {
							// 查询一行数据 多列
							return DBUtil.queryRowColumns(sql, args);
						} else {
							String name = cls.getName();
							/*
							 * for (String t : types) { if (t.equals(name)){
							 * return DBUtil.queryFieldValue(sql,
							 * point.getArgs()); } }
							 */
							if (name.equals(Object.class.getName()))
								return DBUtil.queryFieldValue(sql, args);
							return DBUtil.queryBean(sql, cls, args);
						}
					}
				} else {
					log.debug("执行hql :{} ", sql);
					sqlLog.setSql("HQL : " + sql); // 存储sql
					if (q.update()) {
						if (args != null && args.length > 0)
							return baseDao.executeHql(sql, args);
						else
							return baseDao.executeHql(sql);
					} else {
						if (cls.isAssignableFrom(List.class)) {
							// if (point.getArgs() != null &&
							// point.getArgs().length > 0)
							return q.pager() ? baseDao.findPageByHql(sql, pager, args)
									: baseDao.findByHql(sql, args);
							// else
							// return baseDao.findByHql(sql);
						} else {
							if (args != null && args.length > 0)
								return baseDao.findBean(sql, args);
							else
								return baseDao.findBean(sql);
						}
					}
				}
			} catch (Exception e) {
				sqlLog.setState("error");
				String ex = e.toString();
				String stackTrace = "";
				StackTraceElement[] st = e.getStackTrace();
				int len = st.length > 20 ? 20 : st.length;
				for (int i = 0; i < len; i++) {
					stackTrace += st[i] + "    \r\n";
				}
				sqlLog.setStackTrace(stackTrace);
				sqlLog.setExceptionInfo(ex);
				log.error("<<{}>> 执行sql语句出现错误   error: {} ", clazzName, e);
				throw e;
			} finally {
				try {
					long t = timer.end();
					log.debug("<<{}>> {} end , diff : {} ms", clazzName, methodName, t);
					sqlLog.setTimeDiff(t);
//					saveSqlLog(sqlLog);
					//LogConsumer.sqlLogQueue.add(sqlLog); // 此处使用add方法，不使用put，以免造成线程堵塞，影响系统正常工作
				} catch (Exception e2) {
					log.error("<<{}>> {} 保存sql执行记录日志出现未知错误！ ", clazzName, methodName, e2);
				}
			}
		} else {
			log.debug("方法：{} 没要找到Query注解 ", method.getName());
			// int index = getSqlArgIndex(paramNames);
			Object[] args = point.getArgs();
			// if (index != -1)
			// sqlLog.setSql(args[index].toString()); // 存储sql
			// else
			// throw new EasException(EasException.SQL_ARG_NAME_ERROR);
			return point.proceed(args);
		}

	}

	// @Around("execution (* com.apexedu.eas.util.DBUtil.*(..))")
	public Object dbFilter(ProceedingJoinPoint point) throws Throwable {
		Object[] os = point.getArgs();
		for (int i = 0; i < os.length; i++) {
			Object o = os[i];
			if (String.class.getName().equals(o.getClass().getName())) {
				String str = o.toString();
				Matcher m = p1.matcher(str);
				while (m.find()) {
					String s = m.group(1);
					String v = SysProperty.MAPING.get(s);
					str = str.replaceAll("@" + s, v);
					log.debug("已替换实体名:{} 为数据库表名:{}", s, v);
				}
				if (str.indexOf("@") != -1) {
					Matcher m1 = p2.matcher(str);
					while (m1.find()) {
						String s = m1.group(1);
						String v = SysProperty.MAPING.get(s);
						str = str.replaceAll("@" + s, v);
						log.debug("已替换实体名:{} 为数据库表名:{}", s, v);
					}
				}
				os[i] = str;
			}
		}
		return point.proceed(os);
	}

	@Around("execution (* com.apexedu.*.controller.*.*(..))")
	public Object process(ProceedingJoinPoint point) throws Throwable {
		log.debug("@Around : start");
		Object returnValue = null;
		TAopLog aop = new TAopLog();
		// 设置ID
		aop.setStartTime(DateUtil.getDateTimeFormat(new Date()));
		aop.setId(UUID.randomUUID().toString().replaceAll("\\-", ""));
		aop.setIp(getRemortIp(SysContent.getRequest()));
		LittleTimer timer = new LittleTimer(); // 计时器
		String classType = point.getTarget().getClass().getName();
		Class<?> clazz = Class.forName(classType);
		String clazzName = clazz.getName();
		// String clazzSimpleName = clazz.getSimpleName();
		String methodName = point.getSignature().getName();
		String[] paramNames = getFieldsName(this.getClass(), clazzName, methodName);
		String logContent = writeLogInfo(paramNames, point);
		aop.setParameter(logContent);
		aop.setFunctionName(methodName);
		aop.setClassName(clazzName);
		aop.setState("normal");
		try {
			Object loginUser = SysContent.getSession().getAttribute("loginUser");
			String userId = null;
			// userId.toString();
			if (loginUser != null) {
				userId = ((Map<String, String>) loginUser).get("id");
				// 设置用户ID
				aop.setUserId(Integer.parseInt(userId));
			}
			log.debug("<<{}>> {} start , userid : {}", clazzName, methodName, timer.end());
			log.info("clazzName: " + clazzName + ", methodName:" + methodName + ", param:" + logContent);
			// 用改变后的参数执行目标方法
			returnValue = point.proceed(point.getArgs());
		} catch (Exception e) {
			aop.setState("error");
			String ex = e.toString();
			String stackTrace = "";
			StackTraceElement[] st = e.getStackTrace();
			int len = st.length > 20 ? 20 : st.length;
			for (int i = 0; i < len; i++) {
				stackTrace += st[i] + "    \r\n";
			}
			aop.setStackTrace(stackTrace);
			aop.setExceptionInfo(ex);
			// System.out.println(stackTrace);
			log.error("<<{}>>  error : ", clazzName, e);
			throw e;
		} finally {
			try {
				String returnVal = getFieldsValue(returnValue);
				long t = timer.end();
				log.debug("return : " + returnVal);
				log.debug("<<{}>> {} end , diff : {} ms", clazzName, methodName, t);
				aop.setTimeDiff(t);
				aop.setReturnValue(returnVal);
				saveAopLog(aop);
				//LogConsumer.ctrlLogQueue.add(aop); // 此处使用add方法，不使用put，以免造成线程堵塞，影响系统正常工作
				// org.hibernate.Session sess = baseDao.getCurrentSession(); //
				// sessionFactory.getCurrentSession();
				// if(!sess.getTransaction().isActive())
				// sess.getTransaction().begin();
				/// Transaction tx = sess.beginTransaction();
				// sess.save(aop);
				// sess.getTransaction().commit();
				// tx.commit();
				// sess.flush();
				// sess.close();
			} catch (Exception e2) {
				log.error("<<{}>> {} 保存aop日志出现未知错误！ ", clazzName, methodName, e2);
			}
			log.debug("@Around : end");
		}
		// log.debug("@Around：被织入的目标对象为：" + point.getTarget());
		return returnValue;
	}

	/*
	 * @Before("execution (* com.apexedu.*.controller.*.*(..))") public void
	 * permissionCheck(JoinPoint point) { log.debug("@Before：模拟权限检查...");
	 * log.debug("@Before：目标方法为：" + point.getSignature().getDeclaringTypeName()
	 * + "." + point.getSignature().getName()); log.debug("@Before：参数为：" +
	 * Arrays.toString(point.getArgs())); log.debug("@Before：被织入的目标对象为：" +
	 * point.getTarget()); }
	 * 
	 * @AfterReturning(pointcut="execution (* com.apexedu.*.controller.*.*(..))"
	 * , returning="returnValue") public void log(JoinPoint point, Object
	 * returnValue) { log.debug("@AfterReturning：模拟日志记录功能...");
	 * log.debug("@AfterReturning：目标方法为：" +
	 * point.getSignature().getDeclaringTypeName() + "." +
	 * point.getSignature().getName()); log.debug("@AfterReturning：参数为：" +
	 * Arrays.toString(point.getArgs())); log.debug("@AfterReturning：返回值为：" +
	 * returnValue); log.debug("@AfterReturning：被织入的目标对象为：" +
	 * point.getTarget());
	 * 
	 * }
	 * 
	 * @After("execution (* com.apexedu.*.controller.*.*(..))") public void
	 * releaseResource(JoinPoint point) { log.debug("@After：模拟释放资源...");
	 * log.debug("@After：目标方法为：" + point.getSignature().getDeclaringTypeName() +
	 * "." + point.getSignature().getName()); log.debug("@After：参数为：" +
	 * Arrays.toString(point.getArgs())); log.debug("@After：被织入的目标对象为：" +
	 * point.getTarget()); }
	 */

	private static String writeLogInfo(String[] paramNames, JoinPoint joinPoint) {
		Object[] args = joinPoint.getArgs();
		StringBuilder sb = new StringBuilder();
		// boolean clazzFlag = true;
		for (int k = 0; k < args.length; k++) {
			Object arg = args[k];
			sb.append(paramNames[k] + " ");
			sb.append(": " + getFieldsValue(arg) + "; ");
		}
		return sb.toString();
	}

	private static String writeLogInfo(String[] paramNames, JoinPoint joinPoint, String sqlArgName) {
		Object[] args = joinPoint.getArgs();
		StringBuilder sb = new StringBuilder();
		// boolean clazzFlag = true;
		for (int k = 0; k < args.length; k++) {
			if (!sqlArgName.equals(paramNames[k])) {
				Object arg = args[k];
				sb.append(paramNames[k] + " ");
				sb.append(": " + getFieldsValue(arg) + "; ");
			}
		}
		return sb.toString();
	}

	/**
	 * 得到方法参数的名称
	 * 
	 * @param cls
	 * @param clazzName
	 * @param methodName
	 * @return
	 * @throws NotFoundException
	 */
	private static String[] getFieldsName(Class cls, String clazzName, String methodName) throws NotFoundException {
		ClassPool pool = ClassPool.getDefault();
		// ClassClassPath classPath = new ClassClassPath(this.getClass());
		ClassClassPath classPath = new ClassClassPath(cls);
		pool.insertClassPath(classPath);

		CtClass cc = pool.get(clazzName);
		CtMethod cm = cc.getDeclaredMethod(methodName);
		MethodInfo methodInfo = cm.getMethodInfo();
		CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
		LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
		if (attr == null) {
			// exception
		}
		String[] paramNames = new String[cm.getParameterTypes().length];
		int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
		for (int i = 0; i < paramNames.length; i++) {
			paramNames[i] = attr.variableName(i + pos); // paramNames即参数名
		}
		return paramNames;
	}

	/**
	 * 得到参数的值
	 * 
	 * @param obj
	 */
	public static String getFieldsValue(Object obj) {
		if (obj == null)
			return "null";
		if (Map.class.isAssignableFrom(obj.getClass())) {
			// 遍历map
			Map map = (Map) obj;
			Object[] os = map.entrySet().toArray();
			StringBuilder sb = new StringBuilder();
			sb.append("[");
			for (Object o : os) {
				Map.Entry e = (Entry) o;
				sb.append(e.getKey()).append(" = ").append(e.getValue()).append("; ");
			}
			sb.append("]");
			return sb.toString();
		} else if (ServletRequest.class.isAssignableFrom(obj.getClass())) {
			HttpServletRequest req = (HttpServletRequest) obj;
			Map<String, String[]> map = req.getParameterMap();
			Object[] os = map.entrySet().toArray();
			StringBuilder sb = new StringBuilder();
			sb.append("[");
			for (Object o : os) {
				Map.Entry<String, String[]> e = (Entry<String, String[]>) o;
				sb.append(e.getKey()).append(" = ").append("[");
				String[] str = e.getValue();
				for (String s : str) {
					sb.append(s).append(",");
				}
				if (sb.length() > 0)
					sb.setLength(sb.length() - 1);
				sb.append("] , ");
			}
			if (sb.length() > 1)
				sb.setLength(sb.length() - 2);
			sb.append("]");
			return sb.toString();
		} else {
			Field[] fields = obj.getClass().getDeclaredFields();
			String typeName = obj.getClass().getName();
			for (String t : types) {
				if (t.equals(typeName))
					return obj.toString();
			}
			StringBuilder sb = new StringBuilder();
			sb.append("[");
			for (Field f : fields) {
				f.setAccessible(true);
				try {
					for (String str : types) {
						if (f.getType().getName().equals(str)) {
							Object val = f.get(obj);
							sb.append(f.getName() + " = " + (val == null || "".equals(val) ? "null" : val) + "; ");
						}
					}
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
			sb.append("]");
			return sb.toString();
		}
	}
	private void saveAopLog(TAopLog aop){
		if(enable)
			LogConsumer.ctrlLogQueue.add(aop); // 此处使用add方法，不使用put，以免造成线程堵塞，影响系统正常工作
	}
	private void saveSqlLog(TSqlLog aop){
		if(enable)
			LogConsumer.sqlLogQueue.add(aop); // 此处使用add方法，不使用put，以免造成线程堵塞，影响系统正常工作
	}
	public static String getRemortIp(HttpServletRequest request) {
		if (request == null) {
			// 系统初始化时查询sql
			return "SYSTEM";
		}
		if (request.getHeader("x-forwarded-for") == null) {
			return request.getRemoteAddr();
		}
		return request.getHeader("x-forwarded-for");
	}

	
	public static void main(String[] args) {
		String sq1l ="select * from dual where id in ( #{sql} )";
		Matcher mm = p3.matcher("select * from dual where id in ( #{sql} )");
		while (mm.find()) {
			String s = mm.group(1);
			System.out.println(sq1l.replaceAll("#\\{"+s+"\\}", "test"));
			
		}
		
		
		
		String sql = "select g.KSN,H.codeName XQ,isnull(CONVERT(VARCHAR(5),A.XH),'-') as XH,isnull(A.XSBH,'-') as XSBH,d.KCMC,case when isnull(e.BKCJ,-1)>e.ZPCJ then e.BKCJ else e.ZPCJ end ZPCJ\n"
				+ "from XS0101 a\n" + "left join XS0701 b on a.ID=b.XS\n" + " left join XS0706 e on e.XS=a.ID \n"
				+ "inner join T_JX_TClass c on c.ID=e.JXB\n" + "inner join T_JX_KC d on d.ID=c.KCXX\n"
				+ "left join semester f on f.ID=c.XQ\n" + "left join schoolyear g on g.ID=f.XN\n"
				+ "left join hemi_code h on h.Id=f.XQ\n"
				+ "where a.ID= [id] and d.id!=11 and d.kcmc!='班会'and  d.kcmc!='打字课' and  d.kcmc!='选修课' and  d.kcmc!='学生社团'  and e.qmcjsftj=1\n"
				+ "order by g.XN,f.XNXX,a.XH,d.id";
		System.out.println(sql);
		try {
			Method m = AopLogDao.class.getMethod("getRecordCount", Class.class);

			System.out.println(m.getReturnType().isAssignableFrom(Long.class));
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}